package campus.aiit.ssl.controller;

import campus.aiit.ssl.domain.model.Device;
import campus.aiit.ssl.domain.model.Instruct;
import campus.aiit.ssl.domain.param.BadResult;
import campus.aiit.ssl.domain.param.BadStatusEnum;
import campus.aiit.ssl.manage.modbus.ModBus;
import campus.aiit.ssl.manage.modbus.provider.InstructionPriorityException;
import campus.aiit.ssl.service.DeviceService;
import campus.aiit.ssl.service.InstructService;
import campus.aiit.ssl.service.UserService;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.iflytek.uaac.client.rest.context.UaacServiceContext;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.apache.ibatis.annotations.Param;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.*;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.scheduling.annotation.Schedules;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * @author ihaokun
 * @date 2019/12/11 17:17
 */
@Api(description = "设备相关Api")
@RestController
public class DeviceController {
    @Resource
    private DeviceService deviceService;
    @Resource
    private UserService userService;

    @Autowired
    private RestTemplate restTemplate;

    @Autowired
    private InstructService instructService;

    @ApiOperation("设备（添加）")
    @PostMapping("devices")
    public boolean addDevice(@RequestBody Device device) {
        return deviceService.addDevice(device);
    }


    @ApiOperation("设置人数识别频率")
    @GetMapping("setcorn")
    public String setcorn(@Param("corn") int corn) {
        String uri = "http://127.0.0.1:8100/setcorn?time=" + corn;
        System.out.println(uri);
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON_UTF8);
        HttpEntity<String> entity = new HttpEntity<String>(headers);
        ResponseEntity<String> exchange = restTemplate.exchange(uri, HttpMethod.GET, entity, String.class);

        return exchange.getBody();
    }


    @ApiOperation("时钟同步")
    @GetMapping("timecancel")
    public boolean timecancel(Long deviceid, Long instruid, HttpSession session) {


        Calendar c = Calendar.getInstance();

        int dayForWeek;
        if (c.get(Calendar.DAY_OF_WEEK) == 1) {
            dayForWeek = 7;
        } else {
            dayForWeek = c.get(Calendar.DAY_OF_WEEK) - 1;
        }

        String time = new SimpleDateFormat("yyyyMMddHHmmssSSS").format(new Date());


        System.err.println("十进制时间====》" + time);

        String month = Integer.toHexString(Integer.parseInt(time.substring(4, 6))).length() == 1 ? "0" + Integer.toHexString(Integer.parseInt(time.substring(4, 6))) : Integer.toHexString(Integer.parseInt(time.substring(4, 6)));

        String hour = Integer.toHexString(Integer.parseInt(time.substring(8, 10))).length() == 1 ? ("0" + Integer.toHexString(Integer.parseInt(time.substring(8, 10)))) : (Integer.toHexString(Integer.parseInt(time.substring(8, 10))));

        String minute = Integer.toHexString(Integer.parseInt(time.substring(10, 12))).length() == 1 ? ("0" + Integer.toHexString(Integer.parseInt(time.substring(10, 12)))) : Integer.toHexString(Integer.parseInt(time.substring(10, 12)));

        String second = Integer.toHexString(Integer.parseInt(time.substring(12, 14))).length() == 1 ? ("0" + Integer.toHexString(Integer.parseInt(time.substring(12, 14)))) : Integer.toHexString(Integer.parseInt(time.substring(12, 14)));


        String day = Integer.toHexString(Integer.parseInt(time.substring(6, 8))).length() == 1 ? "0" + Integer.toHexString(Integer.parseInt(time.substring(6, 8))) : Integer.toHexString(Integer.parseInt(time.substring(6, 8)));


        String middletime = Integer.toHexString(Integer.parseInt(time.substring(0, 2)))//年
                + Integer.toHexString(Integer.parseInt(time.substring(2, 4)))//年
                + month//月
                + day//日
                + "0" + Integer.toHexString(dayForWeek)//星期
                + hour//时
                + minute//分
                + second//秒
                + Integer.toHexString(Integer.parseInt(time.substring(14, 16)))//毫秒
                + "0" + Integer.toHexString(Integer.parseInt(time.substring(16, 17)));//毫秒

        String newtime = "1000F200050A" + middletime;


        System.err.println("十六进制时间====》" + middletime);

        Instruct instruct = new Instruct();

        instruct.setId(instruid);

        instruct.setName("时间同步");

        instruct.setTemplateId(3L);

        instruct.setValue(newtime);

        instructService.savetime(instruct);

        boolean b = deviceService.controlByInstructId(deviceid, instruid, session);


        return b;
    }


    //根据人数调节空调温度--人数下发
    @PostMapping("setwendu")
    @ApiOperation("人数下发")
    public boolean setwendu(Long deviceId, Long instructId, HttpSession httpSession) {
        //TODO 人数暂时写死
     final boolean[] b = {new Boolean(false)};
//        String uri = "http://localhost:8100/getpeople";
//        HttpHeaders headers = new HttpHeaders();
//        headers.setContentType(MediaType.APPLICATION_JSON_UTF8);
//        HttpEntity<String> entity = new HttpEntity<String>(headers);
//        ResponseEntity<List> exchange = restTemplate.exchange(uri, HttpMethod.POST, entity, List.class);
//
//
//        exchange.getBody().forEach(o -> {

//                    String s = JSON.toJSONString(o);
//
//                    JSONObject json = JSON.parseObject(s);
//
//
//                    Arrays.asList(json.keySet().toArray()).stream().forEach(e->{

                        //String low8a = Integer.toHexString((int)json.get(e) & 0xff).length() == 1 ? "0" + Integer.toHexString((int)json.get(e) & 0xff) : Integer.toHexString((int)json.get(e) & 0xff);
String low8a= Integer.toHexString(20& 0xff).length() == 1 ? "0" + Integer.toHexString(20 & 0xff) : Integer.toHexString(20& 0xff);
//高八位用一个字节来表示
                        String high8a = Integer.toHexString(20 >> 8).length() == 1 ? "0" + Integer.toHexString(20>> 8) : Integer.toHexString(20>> 8);

                        System.err.println("high8a=============" + high8a);
                        System.err.println("low8a=============" + low8a);

                        String instructvalue = "0600F1" + high8a + low8a;


                        System.out.println(instructvalue);

                        Instruct instruct = new Instruct();

                        instruct.setValue(instructvalue);

                        instruct.setTemplateId(3L);

                        instruct.setId(instructId);

                        instruct.setName("发送人数");

                        instructService.savetime(instruct);

                        b[0] = deviceService.controlByInstructId(deviceId, instructId, httpSession);
//                    });
//                }
//        );
        return b[0];
    }

    //房间人数集合查询
    @ApiOperation("房间人数集合查询")
    @GetMapping("searchcount")
    public List searchcount() {
        String uri = "http://localhost:8100/searchpeoplecount";
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        HttpEntity<String> entity = new HttpEntity<String>(headers);
        ResponseEntity<List> exchange = restTemplate.exchange(uri, HttpMethod.GET, entity, List.class);

        System.out.println(exchange);

        return exchange.getBody();
    }

    @ApiOperation("人数分析")
    @PostMapping("searchpeople")
    public String searchpeople() {
        String uri = "http://localhost:8100/getpeople";
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON_UTF8);
        HttpEntity<String> entity = new HttpEntity<String>(headers);
        ResponseEntity<List> exchange = restTemplate.exchange(uri, HttpMethod.POST, entity, List.class);
        return exchange.getBody().toString();
    }

    //频率查询
    @GetMapping("searchcorn")
    @ApiOperation("人数分析频率查询")
    public String searchcorn() {
        String uri = "http://localhost:8100/searchcorn";
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        HttpEntity<String> entity = new HttpEntity<String>(headers);
        ResponseEntity<String> exchange = restTemplate.exchange(uri, HttpMethod.GET, entity, String.class);
        return exchange.getBody();
    }

    @ApiOperation("设备（数据校验）")
    @PostMapping("devices/importExcel/checkFile")
    public Map<String, Object> checkFile(@RequestParam("file") MultipartFile file) {
        System.out.println("check");
        return deviceService.checkFile(file);
    }

    @ApiOperation("设备（修改）")
    @PutMapping("devices")
    public boolean modifyDevice(@RequestBody Device device) {
        return deviceService.modifyDevice(device);
    }

    @ApiOperation("设备（删除）")
    @DeleteMapping("devices/{id}")
    public boolean removeDevice(@PathVariable long id) {
        return deviceService.removeDevice(id);
    }


    @ApiOperation("设备（列表）：根据区域块/房间Id")
    @GetMapping({
            "devices/blockId",
            "devices/blockId/{blockId}",
            "devices/blockId/{blockId}/{roomId}"
    })
    public Map<String, Object> Blocks(
            @PathVariable(required = false) Long blockId,
            @PathVariable(required = false) Long roomId,
            @RequestParam(defaultValue = "false") boolean isInstant,
            @RequestParam(required = false) Long typeId,
            @RequestParam(required = false) String userId,
            @RequestParam(defaultValue = "1") int pageNum,
            @RequestParam(defaultValue = "10") int pageSize) {
        Map<String, Object> result = new HashMap<>();
        PageHelper.startPage(pageNum, pageSize);
        int roleId = userService.getUserById(userId).getRoleId();
        if (roleId == 0) {
            userId = null;
        }
        List<Map<String, Object>> devices = deviceService.selectByBlock(blockId, roomId, typeId, userId, isInstant);
        result.put("list", devices);
        PageInfo<Map<String, Object>> pageInfo = new PageInfo<>(devices);
        result.put("total", pageInfo.getTotal());
        return result;
    }

    @ApiOperation("设备（列表）：根据校区/楼栋/楼层/房间Id")
    @GetMapping({
            "devices",
            "devices/{zoneId}",
            "devices/{zoneId}/{buildingId}",
            "devices/{zoneId}/{buildingId}/{floor}",
            "devices/{zoneId}/{buildingId}/{floor}/{roomId}"
    })
    public Map<String, Object> devices(
            @PathVariable(required = false) Long zoneId,
            @PathVariable(required = false) Long buildingId,
            @PathVariable(required = false) Long floor,
            @PathVariable(required = false) Long roomId,
            @RequestParam(required = false) Long typeId,
            @RequestParam(defaultValue = "false") boolean isInstant,
            @RequestParam(defaultValue = "1") int pageNum,
            @RequestParam(defaultValue = "10") int pageSize,
            HttpServletRequest request) {
        Map<String, Object> result = new HashMap<>();
        PageHelper.startPage(pageNum, pageSize);
        String userId = null;
        try {
            if (request.getSession().getAttribute("roleId").equals(2)) {
                userId = (String) request.getSession().getAttribute("userId");
            }
        } catch (NullPointerException e) {
            userId = UaacServiceContext.getUaacService().getCurrentUser(request.getSession()).getLoginName();
            int roleId = userService.getUserById(userId).getRoleId();
            if (roleId == 0) {
                userId = null;
            }
        }
        List<Map<String, Object>> devices = deviceService.devices(zoneId, buildingId, floor, roomId, typeId, userId, isInstant);
        result.put("list", devices);
        PageInfo<Map<String, Object>> pageInfo = new PageInfo<>(devices);
        result.put("total", pageInfo.getTotal());
        return result;
    }

    //FIXED 控制项列表和执行，应该是统一的
    @ApiOperation("控制项列表和执行，应该是统一的")
    @GetMapping("/items")
    public List<String> items() {
        return deviceService.items();
    }

    @ApiOperation("设备执行控制项")
    @GetMapping("/devices/perform")
    public boolean performItem(@RequestParam long[] ids, @RequestParam String itemName, HttpSession httpSession) {
        return deviceService.performItem(ids, itemName, httpSession);
    }

    @ApiOperation("设备执行指令")
    @GetMapping("/devices/controlByInstructId")
    public boolean controlByInstructId(@RequestParam Long deviceId, @RequestParam Long instructId, HttpSession httpSession) {
        if(instructId==300){
            boolean b = this.timecancel(deviceId, instructId, httpSession);
            return b;
        }else if (instructId==400){
            boolean b = this.setwendu(deviceId, instructId, httpSession);
            return b;
        }
        return deviceService.controlByInstructId(deviceId, instructId, httpSession);
    }

    @ApiOperation("设备自控（开）")
    @GetMapping("devices/auto/on")
    public boolean autoTurnOn(long[] ids) {
        return deviceService.autoTurnOn(ids);
    }

    @ApiOperation("设备自控（关）")
    @GetMapping("devices/auto/off")
    public boolean autoTurnOff(long[] ids) {
        return deviceService.autoTurnOff(ids);
    }

    @ApiOperation("设备继电器（开）")
    @GetMapping("devices/relay/on")
    public boolean relayTurnOn(long[] ids) {
        return deviceService.relayTurnOn(ids);
    }

    @ApiOperation("设备继电器（关）")
    @GetMapping("devices/relay/off")
    public boolean relayTurnOff(long[] ids) {
        return deviceService.relayTurnOff(ids);
    }

    @ExceptionHandler(ModBus.ADU.PDU.FunctionCodes.ModBusFunctionCodeException.class)
    private String modbusResponseFunCodeException(ModBus.ADU.PDU.FunctionCodes.ModBusFunctionCodeException e) {
        e.printStackTrace();
        return new BadResult(BadStatusEnum.MODBUS_EXCEPTION, e.getMessage()).toString();
    }

    @ExceptionHandler(InstructionPriorityException.class)
    private String instructionPriorityException(InstructionPriorityException e) {
        e.printStackTrace();
        return new BadResult(BadStatusEnum.MODBUS_EXCEPTION, e.getMessage()).toString();
    }

    @ApiOperation("指令（列表）：根据设备类型")
    @GetMapping("instructs")
    public Instruct[] Instructs(Long typeId) {
        return deviceService.Instructs(typeId);
    }
}